// ==UserScript==
// @name         一体化平台
// @namespace    xyz.lisys
// @version      3.30
// @description  一体化平台表格工时对比
// @author       SystemLight
// @match        http://10.34.161.221/IDTS/casLoginIndex*
// @match        http://tfs.piccnet.com.cn:8080/tfs/PICCCollection*
// @match        http://itgw.piccnet.com.cn/list.html*
// @require      https://unpkg.com/axios@1.4.0/dist/axios.min.js
// @grant        none
// ==/UserScript==

;(function () {
    'use strict'

    function findAssignedBy(names) {
        let nameList = names.split(',')
        let resultSet = new Set()
        $('.grid-cell.identity-grid-cell').each(function () {
            let name = $(this).text()
            if (nameList.includes(name)) {
                resultSet.add(name)
            }
        })
        return Array.from(resultSet)
    }

    function findQuerySelect() {
        return $('.ms-List-cell').has('.is-selected').find('.query-name-ellipsis.query-folder').text()
    }

    function openUrls(urls) {
        urls.forEach((url) => window.open(url))
    }

    function findQueryFolder(name) {
        let result = []
        let collectFlag = 0 // 0 未开始 1 开始 2 结束
        try {
            $('.ms-List-cell').each(function () {
                let $node = $(this).find('.query-name-ellipsis')
                let text = $node.text()

                if ($node.hasClass('query-folder')) {
                    if (text === name) {
                        collectFlag = 1
                        return
                    } else if (collectFlag === 1) {
                        collectFlag = 2
                    }
                }

                if (collectFlag === 1) {
                    result.push({
                        text: text,
                        url: $node.find(`a:contains(${text})`).prop('href')
                    })
                } else if (collectFlag === 2) {
                    throw new Error('跳出循环')
                }
            })
        } catch (e) {
        }

        return result
    }

    function isValidDate(date) {
        return date instanceof Date && !isNaN(date.getTime())
    }

    function formatDate(dateString) {
        if (dateString === '@今天') {
            return getDateString(new Date())
        }

        return dateString
    }

    function getDateString(date) {
        return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`
    }

    function nextDate(date) {
        date.setDate(date.getDate() + 1)
        return date
    }

    function lastDate(date) {
        date.setDate(date.getDate() - 1)
        return date
    }

    function setNowDay(dayValue) {
        let $startDate = $('[aria-label="开始日期 字段的值"]')
        let $actualStartTime = $('[aria-label="实际开始时间 字段的值"]')
        let $completionDate = $('[aria-label="完成日期 字段的值"]')

        $startDate.trigger('focus')
        $startDate.val(dayValue)
        $startDate.trigger('blur')

        $actualStartTime.trigger('focus')
        $actualStartTime.val(dayValue)
        $actualStartTime.trigger('blur')

        $completionDate.trigger('focus')
        $completionDate.val(dayValue)
        $completionDate.trigger('blur')
    }

    function getNowDay() {
        let $startDate = $('[aria-label="开始日期 字段的值"]')
        let $actualStartTime = $('[aria-label="实际开始时间 字段的值"]')
        let $completionDate = $('[aria-label="完成日期 字段的值"]')

        return $startDate.val() || $actualStartTime.val() || $completionDate.val()
    }

    function delay(ms) {
        return new Promise((resolve) => {
            setTimeout(function () {
                resolve()
            }, ms)
        })
    }

    function showAllocate(el, sourceRemain, closeCallback) {
        // 创建外层div元素及其样式 allocate-wrap
        const outerDiv = document.createElement('div')
        outerDiv.style.background = '#50b7b7'
        outerDiv.style.position = 'absolute'
        outerDiv.style.left = '-50px'
        outerDiv.style.top = '50%'
        outerDiv.style.transform = 'translateY(-50%)'
        outerDiv.style.padding = '5px'
        outerDiv.style.borderRadius = '5px'
        outerDiv.style.display = 'flex'
        outerDiv.style.width = '400px'
        outerDiv.style.zIndex = '99999'

        // 创建内部元素及其样式
        const allocate = document.createElement('input')
        allocate.type = 'text'
        allocate.style.marginRight = '5px'
        allocate.placeholder = '输入工作时长自动分配'

        const subtract = document.createElement('button')
        subtract.textContent = '-'
        subtract.style.marginRight = '5px'
        subtract.style.padding = '0 15px'

        const add = document.createElement('button')
        add.textContent = '+'
        add.style.marginRight = '5px'
        add.style.padding = '0 15px'

        const remainDiv = document.createElement('div')
        remainDiv.textContent = '补差工时：'
        remainDiv.style.marginRight = '15px'

        const remain = document.createElement('span')
        remain.textContent = sourceRemain

        const closeBtn = document.createElement('button')
        closeBtn.textContent = '关闭'

        // 将内部元素添加到外层div元素
        outerDiv.appendChild(allocate)
        outerDiv.appendChild(subtract)
        outerDiv.appendChild(add)
        remainDiv.appendChild(remain)
        outerDiv.appendChild(remainDiv)
        outerDiv.appendChild(closeBtn)

        add.onclick = function () {
            let allocateValue = Number(allocate.value)
            let remainValue = Number(remain.textContent)
            if (!Number.isNaN(allocateValue) && !Number.isNaN(remainValue)) {
                allocateValue += 0.1
                remainValue -= 0.1

                if (allocateValue <= 3.5) {
                    allocate.value = allocateValue.toFixed(1)
                    remain.textContent = remainValue.toFixed(1)
                    copyText(allocate.value, '复制工时成功')
                }
            }
        }

        subtract.onclick = function () {
            let allocateValue = Number(allocate.value)
            let remainValue = Number(remain.textContent)
            if (!Number.isNaN(allocateValue) && !Number.isNaN(remainValue)) {
                allocateValue -= 0.1
                remainValue += 0.1

                if (allocateValue >= 0) {
                    allocate.value = allocateValue.toFixed(1)
                    remain.textContent = remainValue.toFixed(1)
                    copyText(allocate.value, '复制工时成功')
                }
            }
        }

        closeBtn.onclick = function () {
            closeCallback?.()
            outerDiv.remove()
        }

        allocate.onblur = function () {
            let allocateValue = Number(allocate.value)
            let remainValue = Number(remain.textContent)
            let sourceAllocateValue = allocateValue

            if (allocate.value === '') {
                return
            }

            if (Number.isNaN(allocateValue) || Number.isNaN(remainValue)) {
                showToast('错误数值无法正确分配', 2000)
                return
            }

            if (allocateValue > 3.5) {
                allocate.value = ''
                showToast('工时任务不能超过3.5', 2000)
                allocate.focus()
                return
            } else if (allocateValue < 0) {
                allocate.value = ''
                showToast('工时任务不能为负值或等于0', 2000)
                allocate.focus()
                return
            }

            if (remainValue > 0) {
                // 分配模式
                allocateValue += remainValue

                if (allocateValue > 3.5) {
                    remain.textContent = (remainValue - 3.5 + sourceAllocateValue).toFixed(1)
                    allocate.value = Number(3.5).toString()
                    copyText(allocate.value, '复制工时成功')
                } else {
                    remain.textContent = Number(0).toString()
                    allocate.value = allocateValue.toFixed(1)
                    copyText(allocate.value, '复制工时成功')
                }
            } else {
                // 补充模式
                if (sourceAllocateValue <= 0.5) {
                    allocate.value = ''
                    showToast('补充模式不能提供低于0.5工时', 2000)
                    allocate.focus()
                    return
                }

                allocateValue += remainValue

                if (allocateValue < 0.5) {
                    remain.textContent = (remainValue - 0.5 + sourceAllocateValue).toFixed(1)
                    allocate.value = Number(0.5).toString()
                    copyText(allocate.value, '复制工时成功')
                } else {
                    remain.textContent = Number(0).toString()
                    allocate.value = allocateValue.toFixed(1)
                    copyText(allocate.value, '复制工时成功')
                }
            }
        }

        allocate.onkeypress = function (event) {
            // 判断按下的键是否为回车键
            if (event.keyCode === 13) {
                // 让输入框失去焦点
                event.target.blur()
            }
        }

        // 将外层div元素添加到页面中
        el.appendChild(outerDiv)

        allocate.focus()
    }

    function showToast(message, duration) {
        const wrapper = document.createElement('div') // 创建包裹元素
        const toastElem = document.createElement('div') // 创建提示元素
        toastElem.innerText = message // 添加提示信息
        toastElem.classList.add('toast') // 添加提示元素样式
        wrapper.appendChild(toastElem) // 将提示元素添加到包裹元素中

        const body = document.querySelector('body') // 获取页面 body 元素
        body.appendChild(wrapper) // 添加到页面底部

        setTimeout(() => {
            setTimeout(() => {
                wrapper.remove() // 移除提示元素
            }, 300) // 在动画结束后移除
        }, duration) // 在指定时间后添加淡出动画和移除

        // 设置样式
        wrapper.style.position = 'fixed'
        wrapper.style.top = '30px'
        wrapper.style.left = '50%'
        wrapper.style.transform = 'translate(-50%, -50%)'
        wrapper.style.width = '300px'
        wrapper.style.padding = '10px'
        wrapper.style.background = '#E6A23C'
        wrapper.style.color = 'white'
        wrapper.style.borderRadius = '8px'
        wrapper.style.zIndex = '99999'
        toastElem.style.wordBreak = 'break-all'
    }

    function copyText(text, msg) {
        const input = document.createElement('input')
        input.setAttribute('readonly', 'readonly')
        input.setAttribute('value', text)
        document.body.appendChild(input)

        input.select()
        input.setSelectionRange(0, input.value.length)

        document.execCommand('copy')

        document.body.removeChild(input)

        showToast(msg || '复制成功', 2000)
    }

    function loadIframe(iframe, callback) {
        if (iframe) {
            iframe.onload = function () {
                callback(iframe.contentDocument, iframe.contentWindow)
            }
        }
    }

    function removeColumn(table, column) {
        const rows = table.rows
        for (let i = 0; i < rows.length; i++) {
            const cells = rows[i].cells
            cells[column].remove()
        }
    }

    function gotoRemoveTable() {
        let t = document
            .querySelector('[src="/IDTS/attendance/attendanceDetailsManagement"]')
            .contentDocument.querySelector('table')
        comparaData(t, 11, 12, 10)
    }

    function comparaData(table, one, two, three) {
        // 获取所有行
        let rows = table.rows

        rows[0].cells[15].style.cursor = 'pointer'

        rows[0].cells[15].onclick = function () {
            alert(
                `超出总时长：${[...rows]
                    .slice(1)
                    .map((item) => Number(item.cells[16].textContent))
                    .filter((item) => !Number.isNaN(item))
                    .reduce((a, b) => a + b)
                    .toFixed(1)}`
            )
        }

        // 遍历每一行
        for (let i = 0; i < rows.length; i++) {
            // 获取该行的所有列
            let cells = rows[i].cells
            rows[i].style.position = 'relative'

            if (i === 0) {
                // 如果不一致，标记为红色
                cells[one].style.color = 'blue'
                cells[two].style.color = 'blue'
                cells[three].style.color = 'blue'

                let td = document.createElement('th')
                td.textContent = '补差工时'

                let parent = cells[two].parentNode // 获取已有 li 元素的父节点
                let nextSibling = cells[two].nextSibling // 获取已有 li 元素的下一个兄弟元素
                parent.insertBefore(td, nextSibling) // 插入新元素到已有元素后面

                continue
            }

            // 获取第三列和第四列的数据
            let col1 = Number(cells[one].textContent)
            let col2 = Number(cells[two].textContent)
            let col3 = Number(cells[three].textContent)

            //col1 = parseInt(col1 * 10) / 10 // 直接进位保留一位小数点
            let _col2 = parseInt(col2 * 10) / 10 // 直接进位保留一位小数点

            let td = document.createElement('td')
            let diffValue = (col1 - _col2).toFixed(1)
            td.textContent = isNaN(diffValue) ? '--' : diffValue

            let parent = cells[two].parentNode // 获取已有 li 元素的父节点
            let nextSibling = cells[two].nextSibling // 获取已有 li 元素的下一个兄弟元素
            parent.insertBefore(td, nextSibling) // 插入新元素到已有元素后面

            if (!(col2<=col1&&col2>=col3)) {
                // 如果不一致，标记为红色
                cells[one].style.color = 'red'
                cells[two].style.color = 'red'
                cells[three].style.color = 'red'
            }

            cells[one].title = col1

            if (col2 > _col2) {
                cells[two].style.background = 'blue'
            }

            if (isFinite(diffValue) && diffValue > 0) {
                td.style.color = '#67C23A'

                cells[two].style.cursor = 'pointer'
                cells[two + 2].style.position = 'relative'

                let isClick = false
                cells[two].onclick = function () {
                    if (!isClick) {
                        isClick = true
                        rows[i].style.backgroundColor = '#909399'
                        copyText(cells[6].textContent.replace(/-/g, '/'), '复制日期成功')
                        showAllocate(cells[two + 2], Number(td.textContent), function () {
                            isClick = false
                        })
                    }
                }
            }

        }
    }

    function getFirstAndLastDayOfMonth(year, month) {
        const startDate = new Date(Date.UTC(year, month - 1, 1)) // 获取当月第一天
        const endDate = new Date(Date.UTC(year, month, 0)) // 获取当月最后一天

        const startYear = startDate.getUTCFullYear()
        const startMonth = startDate.getUTCMonth() + 1
        const startDay = startDate.getUTCDate()

        const endYear = endDate.getUTCFullYear()
        const endMonth = endDate.getUTCMonth() + 1
        const endDay = endDate.getUTCDate()

        return [`${startYear}/${startMonth}/${startDay}`, `${endYear}/${endMonth}/${endDay}`]
    }

    function autoDate() {
        loadIframe(
            document.querySelector('[src="/IDTS/attendance/attendanceDetailsManagement"]'),
            function (document, win) {
                const now = new Date() // 创建一个 Date 对象，表示当前时间
                const year = now.getFullYear() // 获取当前年份
                const month = now.getMonth() + 1 // 获取当前月份，需要加 1

                const [firstDay, lastDay] = getFirstAndLastDayOfMonth(year, month)
                let inputStart = document.getElementById('punch_datestart')
                let inputEnd = document.getElementById('punch_dateend')

                let toPageSize = document.getElementById('toPageSize')
                if (toPageSize && toPageSize.value != '100') {
                    toPageSize.value = '100'
                    win.changePageSize('comForm', 'toPageSize')
                }

                if (!inputStart.value) inputStart.value = firstDay
                if (!inputEnd.value) inputEnd.value = lastDay

                gotoRemoveTable()
            }
        )
    }

    function getTfsAllHours() {
        try {
            let taskDoms = [
                ...document.querySelectorAll(
                    '.vss-PivotBar--content.triage-view-hub-pivot-content:not(.hide-content) .grid-canvas:not(.grid-canvas-droppable) .grid-row .grid-cell:last-child'
                )
            ]
            let sum = taskDoms
                .map((item) => Number(item.textContent))
                .filter((item) => !Number.isNaN(item) && item)
                .reduce((a, b) => a + b)
                .toFixed(1)
            alert(`总任务：${taskDoms.length}，总工时：${sum}`)
        } catch (e) {
            alert('请修改 列选项 添加 已完成工作 到最后一项')
        }
    }

    function clickTfsTaskRow(index) {
        let taskDoms = [
            ...document.querySelectorAll(
                '.vss-PivotBar--content.triage-view-hub-pivot-content:not(.hide-content) .grid-canvas:not(.grid-canvas-droppable) .grid-row'
            )
        ]
        $(taskDoms[index]).trigger('mouseover').trigger('mousedown')
    }

    function inputTfsTaskContent(content) {
        let headTitleInput = document.querySelector(
            '.work-item-form-container .work-item-form-main-header .work-item-form-title input'
        )
        let bodyDescInput = document.querySelector(
            '.work-item-form-container .form-body .lean-rooster.rooster-editor[contenteditable="true"]'
        )
        $(bodyDescInput).html(
            `<div><span style="background-color:rgb(255, 255, 255); display:inline !important"></span>${content}</div>`
        )
        $(headTitleInput).val(content).trigger('keyup')
    }

    function findTfsFormControl(findText) {
        return [...document.querySelectorAll('.form-body .control')].find((dom) => dom.innerText === findText)
    }

    function getTfsTaskType() {
        return findTfsFormControl('任务类型').querySelector('input').value
    }

    function createMenus() {
        let open = false

        let menusDom = document.createElement('div')
        menusDom.style.cssText = `
          position: fixed;
          right: 10px;
          top: 10px;
          transition: height 1s;
          height: 0;
          overflow: hidden;
          z-index: 99999;
          background: #ffffff;
      `

        let menusDomUl = document.createElement('ul')
        menusDom.append(menusDomUl)
        menusDomUl.style.cssText = `
          box-sizing: border-box;
          margin: 0;
          padding: 0;
          height: 100%;
          border: 1px solid #333333;
          overflow-y: auto;
      `

        let shareQueryLi = document.createElement('li')
        menusDomUl.append(shareQueryLi)
        shareQueryLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        shareQueryLi.textContent = '一键查询'
        shareQueryLi.onclick = function () {
            let selectText = findQuerySelect()
            if (selectText) {
                openUrls(findQueryFolder(selectText).map((item) => item.url))
            } else {
                showToast('请选择一个查询文件夹', 2000)
            }
        }

        let screeningPersonnelLi = document.createElement('li')
        menusDomUl.append(screeningPersonnelLi)
        screeningPersonnelLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        screeningPersonnelLi.textContent = '筛查人员'
        screeningPersonnelLi.onclick = function () {
            let result = findAssignedBy(window.prompt('查询名字列表，使用英文逗号隔开'))
            if (result.length) {
                alert(`存在 ${result.join(',')} 几人错误`)
            } else {
                showToast('不存在筛选人员', 2000)
            }
        }

        let calculateWorkHoursLi = document.createElement('li')
        menusDomUl.append(calculateWorkHoursLi)
        calculateWorkHoursLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        calculateWorkHoursLi.textContent = '计算工时'
        calculateWorkHoursLi.onclick = function () {
            getTfsAllHours()
        }

        let syncTaskLi = document.createElement('li')
        menusDomUl.append(syncTaskLi)
        syncTaskLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        syncTaskLi.textContent = '同步任务'
        syncTaskLi.onclick = function () {
            syncTask()
        }

        let nextDayLi = document.createElement('li')
        menusDomUl.append(nextDayLi)
        nextDayLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        nextDayLi.textContent = '下一天'
        nextDayLi.onclick = function () {
            let nowDay = new Date(formatDate(getNowDay()))
            if (!isValidDate(nowDay)) {
                showToast('请使用标准的日期计数法，如2000/01/01', 2000)
                return
            }
            setNowDay(getDateString(nextDate(nowDay)))
            $('[name="运行查询"]').trigger('click')
        }

        let nowDayLi = document.createElement('li')
        menusDomUl.append(nowDayLi)
        nowDayLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        nowDayLi.textContent = '今天'
        nowDayLi.onclick = function () {
            setNowDay('@今天')
            $('[name="运行查询"]').trigger('click')
        }

        let lastDayLi = document.createElement('li')
        menusDomUl.append(lastDayLi)
        lastDayLi.style.cssText = `
          list-style: none;
          padding: 15px;
          border-bottom: 1px solid #3dd5f3;
          cursor: pointer;
      `
        lastDayLi.textContent = '上一天'
        lastDayLi.onclick = function () {
            let nowDay = new Date(formatDate(getNowDay()))
            if (!isValidDate(nowDay)) {
                showToast('请使用标准的日期计数法，如2000/01/01', 2000)
                return
            }
            setNowDay(getDateString(lastDate(nowDay)))
            $('[name="运行查询"]').trigger('click')
        }

        document.body.append(menusDom)

        return {
            toggleOpen() {
                if (open) {
                    this.close()
                } else {
                    this.open()
                }
            },
            open() {
                menusDom.style.height = '300px'
                open = true
                localStorage.setItem('一体化/openStatus', '1')
            },
            close() {
                menusDom.style.height = '0'
                open = false
                localStorage.setItem('一体化/openStatus', '0')
            }
        }
    }

    async function syncTask() {
        try {
            let res = await axios.get('http://localhost:8880/api/data')

            let key = `星期${'日一二三四五六'.charAt(new Date().getDay())}`
            let weekly = res.data.data.find((item) => item.weekText === key)

            let index = 0
            for (let task of weekly.tasks) {
                clickTfsTaskRow(index)
                await delay(1000)
                inputTfsTaskContent(`【${getTfsTaskType()}】${task.text}`)
                await delay(1000)
                index++
            }
        } catch (e) {
            showToast('请开启上班管理系统', 2000)
        }
    }

    function initTfs() {
        // 创建按钮元素
        let button = document.createElement('button')
        let menusDom = createMenus()

        // 设置文本内容
        button.innerHTML = '菜单'

        // 设置样式
        button.style.backgroundColor = 'lightblue'
        button.style.color = 'white'
        button.style.borderRadius = '50%'
        button.style.position = 'fixed'
        button.style.right = '20px'
        button.style.bottom = '20px'
        button.style.width = '60px'
        button.style.height = '60px'
        button.style.border = 'none'
        button.style.outline = 'none'
        button.style.cursor = 'pointer'

        // 添加到页面中
        document.body.appendChild(button)

        let openStatus = localStorage.getItem('一体化/openStatus') === '1'
        if (openStatus) {
            menusDom.open()
        }

        button.onclick = function () {
            menusDom.toggleOpen()
        }
    }

    function initSSO() {
        // 获取需要监听变化的元素
        const target = document.querySelector('.tab-content')

        // 创建一个 Observer 实例，指定回调函数
        const observer = new MutationObserver(function (mutations) {
            autoDate()
        })

        // 配置需要观察的内容类型及其子节点是否要观察
        const config = {
            childList: true
        }

        // 启动监听
        observer.observe(target, config)
    }

    function initClockIn() {
        $('#C12').click()

        setTimeout(function () {
            let result = false
            while (!result) {
                result = confirm('是否确定已经打卡')
                if (result) {
                    axios.get('http://localhost:8880/api/clock/up').then(() => {
                        alert('打卡已记录')
                    })
                }
            }
        }, 2000)
    }

    window.addEventListener('load', () => {
        if (location.origin === 'http://tfs.piccnet.com.cn:8080') {
            initTfs()
        } else if (location.origin === 'http://itgw.piccnet.com.cn') {
            initClockIn()
        } else {
            initSSO()
        }
    })
})()
